package cn.uncode.springcloud.starter.web.result;

import java.io.Serializable;
import java.util.Map;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;

/**
 * 统一API响应结果封装
 *
 * @author Juny
 */
@Getter
@Setter
@ToString
@ApiModel(description = "返回信息")
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class RExt<T> implements Serializable {

	private static final long serialVersionUID = 1L;

	private static int SUCCESS_CODE = ResultCode.SUCCESS.getCode();
	private static int FAILURE_CODE = ResultCode.FAILURE.getCode();
	
	@ApiModelProperty(value = "状态码", required = true)
	private int code;
	@ApiModelProperty(value = "承载数据")
	private T data;
	@ApiModelProperty(value = "返回消息", required = true)
	private String message;
	@ApiModelProperty(value = "成功", required = true)
	private boolean success;
	@ApiModelProperty(value = "分页消息")
	private Map<String, Object> page;
	
	
	public static void setDefaultSuccessCode(int successCode) {
		SUCCESS_CODE = successCode;
	}
	
	public static void setDefaultFailureCode(int failureCode) {
		FAILURE_CODE = failureCode;
	}
	
	public int getCode() {
		return code;
	}
	
	public String getMessage() {
		return message;
	}


	private RExt(ResultCode resultCode) {
		this(resultCode.getCode(), resultCode.getMessage());
	}

	private RExt(ResultCode resultCode, String msg) {
		this(resultCode.getCode(), msg);
	}

	private RExt(ResultCode resultCode, T data) {
		this(resultCode, data, resultCode.getMessage());
	}

	private RExt(ResultCode resultCode, T data, String msg) {
		this(resultCode.getCode(), data, msg);
	}



	private RExt(int code, String message) {
		this.code = code;
		this.message = message;
		appendSuccess(code);
	}

	private void appendSuccess(int code) {
		if(code >= 200 && code < 300) {
			this.success = true;
		}
	}

	private RExt(int code, T data, String message) {
		this.code = code;
		this.message = message;
		this.data = data;
		appendSuccess(code);
	}
	
	private RExt(int code, P<T> page, String message) {
		this.code = code;
		this.message = message;
		this.data = page.getData();
		this.page = page.getPage();
		appendSuccess(code);
	}

	/**
	 * 返回R
	 *
	 * @param code 状态码
	 * @param data 数据
	 * @param msg  消息
	 * @param <T>  T 泛型标记
	 * @return R
	 */
	public static <T> RExt<T> success(int code, T data, String msg) {
		return new RExt<>(code, data, data == null ? RConstant.DEFAULT_NULL_MESSAGE : msg);
	}

	/**
	 * 返回R
	 *
	 * @param data 数据
	 * @param msg  消息
	 * @param <T>  T 泛型标记
	 * @return R
	 */
	public static <T> RExt<T> success(T data, String msg) {
		return success(SUCCESS_CODE, data, msg);
	}
	
	public static <T> RExt<T> success(P<T> page, String msg) {
		return new RExt<T>(SUCCESS_CODE, page, msg);
	}

	/**
	 * 返回R
	 *
	 * @param data 数据
	 * @param resultCode  rcode
	 * @param <T>  T 泛型标记
	 * @return R
	 */
	public static <T> RExt<T> success(T data, ResultCode resultCode) {
		return success(resultCode.getCode(), data, resultCode.getMessage());
	}

	/**
	 * 返回R
	 *
	 * @param data 数据
	 * @param <T>  T 泛型标记
	 * @return R
	 */
	public static <T> RExt<T> success(T data) {
		return success(data, RConstant.DEFAULT_SUCCESS_MESSAGE);
	}
	
	public static <T> RExt<T> success() {
		return success(RConstant.DEFAULT_SUCCESS_MESSAGE);
	}
	
	public static <T> RExt<T> success(P<T> page) {
		return success(page, RConstant.DEFAULT_SUCCESS_MESSAGE);
	}

	/**
	 * 返回R
	 *
	 * @param msg 消息
	 * @param <T> T 泛型标记
	 * @return R
	 */
	public static <T> RExt<T> success(String msg) {
		return new RExt<>(SUCCESS_CODE, msg);
	}

	/**
	 * 返回R
	 *
	 * @param resultCode 业务代码
	 * @param <T>        T 泛型标记
	 * @return R
	 */
	public static <T> RExt<T> success(ResultCode resultCode) {
		return new RExt<>(resultCode);
	}

	/**
	 * 返回R
	 *
	 * @param resultCode 业务代码
	 * @param msg        消息
	 * @param <T>        T 泛型标记
	 * @return R
	 */
	public static <T> RExt<T> success(ResultCode resultCode, String msg) {
		return new RExt<>(resultCode, msg);
	}

	/**
	 * 返回R
	 *
	 * @param msg 消息
	 * @param <T> T 泛型标记
	 * @return R
	 */
	public static <T> RExt<T> failure(String msg) {
		return new RExt<>(FAILURE_CODE, msg);
	}
	
	public static <T> RExt<T> failure() {
		return new RExt<>(FAILURE_CODE, RConstant.DEFAULT_FAILURE_MESSAGE);
	}


	/**
	 * 返回R
	 *
	 * @param code 状态码
	 * @param msg  消息
	 * @param <T>  T 泛型标记
	 * @return R
	 */
	public static <T> RExt<T> failure(int code, String msg) {
		return new RExt<>(code, msg);
	}

	/**
	 * 返回R
	 *
	 * @param resultCode 业务代码
	 * @param <T>        T 泛型标记
	 * @return R
	 */
	public static <T> RExt<T> failure(ResultCode resultCode) {
		return new RExt<>(resultCode);
	}

	/**
	 * 返回R
	 *
	 * @param resultCode 业务代码
	 * @param msg        消息
	 * @param <T>        T 泛型标记
	 * @return R
	 */
	public static <T> RExt<T> failure(ResultCode resultCode, String msg) {
		return new RExt<>(resultCode, msg);
	}
	
	/**
	 * 空
	 * @return
	 */
	public static <T> RExt<T> none() {
		return new RExt<>();
	}




}
